package com.bridgeQQ.client.control.glue
{
	import com.bridgeQQ.client.events.WindowEvent;
	import com.bridgeQQ.client.view.window.glue.GlueHolder;
	
	import flash.display.Screen;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	import mx.core.Application;
	import mx.core.UIComponent;
	import mx.core.Window;
	import mx.events.FlexNativeWindowBoundsEvent;

	public class GlueWindowManager
	{
		private var root:Application;
		
		private var glueClients:Array = [];
		
		private var glueHolders:Array = [];
		
		private var hitRecords:Array = [];
		
		public function GlueWindowManager(application:Application)
		{
			this.root = application;
			this.root.addEventListener(WindowEvent.CREATE, onWindoCreated);
			this.root.addEventListener(WindowEvent.DESTROY, onWindoClosed);
		}
		
		private function makeGlue(holderProxy:IGlueWindowHolderProxy, client:IGlueWindowClient, 
		    position:int):IGlueWindowHolder
		{
			var index:int = position < 0 ? 0 :  -1;
			var holder:IGlueWindowHolder;
			if(holderProxy is IGlueWindowHolder)
			{
				holder = IGlueWindowHolder(holderProxy);
			}
			else
			{
				holder = createGlueHolder();
				if(holderProxy is IGlueWindowClient)
				{
					holder.addClientAt(IGlueWindowClient(holderProxy));
				}
			}		
			holder.addClientAt(client, index);
			var dragArea:UIComponent = client.dragComponent;
			if(dragArea != null)
			{
				dragArea.addEventListener(MouseEvent.MOUSE_DOWN, onClientMoveDown);
			}
			return holder;
		}
		
		private function createGlueHolder():IGlueWindowHolder
		{
			trace("create holder");
			var holder:IGlueWindowHolder = new GlueHolder();
			Window(holder).open();
			return holder;
		}
		
		private function splitGlue(holder:IGlueWindowHolder, clientIndex:int):IGlueWindowHolderProxy
		{
			var clients:Array = holder.splitClient(clientIndex);
			if(clients.length <= 0)
			{
				return null;
			}
			if(clients.length == 1)
			{
				var client:IGlueWindowClient = clients[0];
				client.switchToWindow();
				return client as IGlueWindowHolderProxy;
			}
			var first:IGlueWindowHolderProxy = clients[0] as IGlueWindowHolderProxy;
			if(!first)
			{
				return null;
			}
			var index:int = 1;
			var count:int = clients.length;
			while(index < count)
			{
				makeGlue(first, clients[index] as IGlueWindowClient, 1);
				index ++;
			}
			return first;
		}
		
		private function onClientMoveDown(event:Event):void
		{
			event.currentTarget.addEventListener(MouseEvent.MOUSE_MOVE, onClientMove);
			event.currentTarget.addEventListener(MouseEvent.MOUSE_UP, cancelMove);
		}
		
		private function cancelMove(event:Event):void
		{
			event.currentTarget.removeEventListener(MouseEvent.MOUSE_MOVE, onClientMove);
			event.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, cancelMove);
		}
		
		private function onClientMove(event:MouseEvent):void
		{
			event.currentTarget.removeEventListener(MouseEvent.MOUSE_DOWN, onClientMoveDown);
			event.currentTarget.removeEventListener(MouseEvent.MOUSE_MOVE, onClientMove);
			trace("onClientMove: " + event.currentTarget);			
			var result:IGlueWindowClient;
			var newHolder:IGlueWindowHolderProxy;
			for(var i:int = glueClients.length - 1; i >= 0; i--)
			{
				var client:IGlueWindowClient = glueClients[i];
				if(client.dragComponent == event.currentTarget)
				{
					result = client;
					break;
				}
			}
			for(i = glueHolders.length - 1; i >= 0; i--)
			{
				var holder:IGlueWindowHolder = glueHolders[i] as IGlueWindowHolder;
				if(holder == null)
				{
					continue;
				}
				var index:int = holder.findClientIndex(result);
				if(index >= 0)
				{
					newHolder = splitGlue(holder, index);
					break;
				}
			}
			if(newHolder)
			{
				newHolder.startMove();
			}
		}
		
		private function addGlueWindow(glue:Window):void
		{
			if(glue is IGlueWindowClient)
			{
				operateArray(glueClients, glue, "add");
				glue.addEventListener(FlexNativeWindowBoundsEvent.WINDOW_MOVE, onMove);
			}
			if(glue is IGlueWindowHolderProxy)
			{	
				operateArray(glueHolders, glue, "add");
			}
		}
		
		private function removeGlueWindow(glue:Window):void
		{	
			if(glue is IGlueWindowClient)
			{
				operateArray(glueClients, glue, "remove");
				glue.removeEventListener(FlexNativeWindowBoundsEvent.WINDOW_MOVE, onMove);
			}
			if(glue is IGlueWindowHolderProxy)
			{	
				operateArray(glueHolders, glue, "remove");
			}
		}
		
		private function onMove(event:FlexNativeWindowBoundsEvent):void
		{
			var target:IGlueWindowClient = event.currentTarget as IGlueWindowClient;
			if(target && target.displayStatus == "glue")
			{
				return;
			}
			var rect:Rectangle = event.afterBounds;
			for(var i:int = glueHolders.length - 1; i >= 0; i--)
			{
				var holder:IGlueWindowHolderProxy = glueHolders[i];
				if(holder is IGlueWindowClient && IGlueWindowClient(holder).displayStatus == "glue")
				{
					continue;
				}
				var pos:int = holder.hit(rect);
				if(pos != int.MAX_VALUE)
				{ 
					var lastHit:int = getLastClientHolderHit(target, holder);
					if(lastHit != int.MAX_VALUE && Math.abs(lastHit) > Math.abs(pos))
					{
						makeGlue(holder, target, pos);
						clearClientHolderHit(target);
						break;
					}
					recordClientHolderHit(target, holder, pos);					
				}				
			}
		}
		
		private function recordClientHolderHit(client:IGlueWindowClient, 
		    holder:IGlueWindowHolderProxy, pos:int):void
		{
			//record {client: client, holder: holder, hit: pos}
			hitRecords.push({client: client, holder: holder, hit: pos});
		}
		
		private function getLastClientHolderHit(client:IGlueWindowClient, 
		    holder:IGlueWindowHolderProxy):int
		{
			for(var i:int = hitRecords.length - 1; i >= 0; i--)
			{
				var temp:Object = hitRecords[i];
				if(temp.client == client && temp.holder == holder)
				{
					return temp.hit;
				}
			}
			return int.MAX_VALUE;
		}
		
		private function clearClientHolderHit(client:IGlueWindowClient):void
		{
			for(var i:int = hitRecords.length - 1; i >= 0; i--)
			{
				var temp:Object = hitRecords[i];
				if(temp.client == client)
				{
					hitRecords.splice(i, 1);
				}
			}
		}
		
		
		private function onWindoCreated(event:WindowEvent):void
		{	
			var window:Window = event.window;
			addGlueWindow(window);
			//自动把新生成的 GlueWindow加入到glue
			if(!(window is IGlueWindowClient))
			{
				return;
			}
			var bottom:int = Screen.mainScreen.bounds.height;
			for(var i:int = glueHolders.length - 1; i >= 0; i--)
			{
				var holder:IGlueWindowHolderProxy = glueHolders[i];
				if(holder != window && holder is Window && 
				    ((bottom - Window(holder).height - Window(holder).nativeWindow.bounds.y) >  window.height) )
				{
					makeGlue(holder, IGlueWindowClient(window), 1);
					break;
				}
			}
		}
		
		private function onWindoClosed(event:WindowEvent):void
		{
			var window:Window = event.window;
			if(window is IGlueWindowClient || window is IGlueWindowHolder)
			{
				removeGlueWindow(window);
			}
		}
		
		private function operateArray(array:Array, item:Object, operate:String):int
		{
			var index:int = array.indexOf(item);
			switch(operate)
			{
				case "add":
				    if(index < 0)
					{
						array.push(item);
						index = array.length - 1;
					}
				    break;
				case "remove":
				    if(index >= 0)
					{
						array.splice(index, 1);
					}
				    break;
			}
			return index;
		}
	}
}